#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
    simpledms - main GUI startfile
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    :copyleft: 2008 by Jens Diemer, see AUTHORS for more details.
    :license: GNU GPL v3 or above, see LICENSE for more details.
"""

import os
import sys
import time
import datetime
from pprint import pprint

import Tkinter as tk
import tkMessageBox
from idlelib import textView
from ScrolledText import ScrolledText

from main import fields, sharedTkinter, virtualizeDialog, FilesystemItem
from main.remove_metaDialog import RemoveMetaDialog
from main.setupfieldsDialog import SetupFieldsDialog
from main.edit_raw_configDialog import RawConfigEditDialog

from tools import context_menu, os2

from externals.tkinter_tools.automenu import automenu
from externals.pyconfig import PyConfig

HELP_FILENAME = "README.txt"
CONFIG_PATH = os.path.join(os.path.expanduser("~"), "simpledms.cfg")




DEFAULT_CONFIG = {
    "date format": { # Format information for a datetime.date() field
        "format": "%d.%m.%Y",
        "verbose": "DD.MM.YYYY",
    },
    "datetime format": { # Format information for a datetime.datetime() field
        "format": "%H:%M:%S %d.%m.%Y",
        "verbose": "HH:MM:SS DD.MM.YYYY",
    },
    "meta items": {
        "target" : {
            "field": fields.MultipleChoiceField.__name__,
            "help text": "project target e.g. person/company",
        },
        "category" : {
            "field": fields.MultipleChoiceField.__name__,
            "help text": "",
        },
        "tags" : {
            "field": fields.TagField.__name__,
            "help text": "Comma separated words."
        },
        "status" : {
            "field": fields.SingleChoiceField.__name__,
            "help text": "status e.g. preview, final, release, public"
        },
        "date" : {
            "field": fields.DateField.__name__,
            "help text": "The project date (DD.MM.YYYY)",
        },
        FilesystemItem.ITEM_CREATE_DATE : {
            "field": fields.DatetimeField.__name__,
            "changeable": False, # Optional
            "help text": "create datetime of the file/directory.",
        },
        FilesystemItem.META_CREATE_DATE : {
            "field": fields.DatetimeField.__name__,
            "changeable": False, # Optional
            "help text": "create datetime of the meta data.",
        },
    },
    "choice cache": {
        "target" : ["Mrs. foo", "Mr. bar", "Dr. Foobar"],
        "type": ["preview", "final", "release", "public"],
    }
}
#try:
#    os.remove(CONFIG_PATH) # DEBUG!!!
#except:
#    pass






class SimpledmsApp(object):
    """Die Beispielanwendung."""

    def __init__(self, cmd_args):
        self.root = tk.Tk()
        self.root.title("simpledms")

        # Read config
        self.cfg = PyConfig(
            filename=CONFIG_PATH, verbose=1, defaults=DEFAULT_CONFIG
        )

        # create main menu
        menudata = (
            [
                "_File", (
#                    ("_New", "Control-n", self.new),
#                    ("_Open...", "Control-o", self.open),
#                    ("_Save", "Control-s", self.dummy),
                    (), # Add a separator here
                    ("_Exit","Alt-F4", self.destroy),
                ),
            ],
            [
                "_Actions", (
                    ("_Create virtualize directory", "", self.create_virtualize),
                    ("_Delete virtualize directory", "", self.delete_virtualize),
                    ("_Remove meta files", "", self.remove_meta),
                ),
            ],
            [
                "_Options", (
                    ("_Edit raw config", "", self.edit_raw_config),
#                    ("_Setup fields", "", self.setup_fields),
                ),
            ],
            [
                "_Install", (
                    ("_Add into explorer context menu", "", self.install),
                    ("_Remove from context menu", "", self.deinstall),
                ),
            ],
            [
                "_Help", (
                    ("_Help", "F1", self.help_dialog),
                    (), # Add a separator here
                    ("_About", "", self.about),
                )
            ],
        )
        automenu(self.root, menudata)

        # check the given commandline arguments and display them
        self.fs_items = self.display_picked_items(cmd_args)

        self.create_input_fields()

        # Create Buttons
        buttonframe = tk.Frame(self.root)

        button = tk.Button(buttonframe, text = "validate", command = self.validate)
        button.pack(side=tk.LEFT)

        button = tk.Button(buttonframe, text = "save", command = self.save)
        button.pack(side=tk.LEFT)

        button = tk.Button(buttonframe, text = "cancel", command = self.destroy)
        button.pack(side=tk.LEFT)

        buttonframe.pack(fill=tk.X)

        self.check_cfg()
        
        # Set path to junction.exe in tools.os2
        os2.JUNCTION_EXE = self.cfg["junction.exe"]

        self.root.mainloop()

    #--------------------------------------------------------------------------
    
    def check_cfg(self):
        """
        Check/set some config data
        """
        if sys.platform == "win32":
            # Check/set path to sysinternals 'junction.exe'
            # http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx
            junction = self.cfg.get("junction.exe", None)
            new_path = sharedTkinter.askfilepath(
                title="Path to sysinternal's 'junction.exe':",
                initialfile="junction.exe",
                oldpath=junction
            )
            if new_path != junction:
                self.cfg["junction.exe"] = new_path
                self.cfg.save()
    
    #--------------------------------------------------------------------------

    def display_picked_items(self, cmd_args):
        """
        Create a list of all picked filesystem items
        """
        tk.Label(self.root, text="Picked filesystem items:").pack()

        fs_items = []
        for cmd_arg in cmd_args:
            try:
                item = FilesystemItem.FilesystemItem(cmd_arg)
            except FilesystemItem.SkipMetaFile:
                # Skip all .meta files
                continue
            item.debug()
            fs_items.append(item)

        # Create a ScrolledText and insert all fs_items
        sharedTkinter.add_fs_items(self.root, fs_items)

        return fs_items

    def create_input_fields(self):
        """
        Create the meta input fields
        """
        self.fields = {}

        for meta_name, meta_cfg in self.cfg["meta items"].iteritems():
            print " -"*79
            print meta_name

            field_name = meta_cfg["field"]
            print "field:", field_name
            Field = getattr(fields, field_name)
            print "Field class:", Field

            fs_item_data = []
            for fs_item in self.fs_items:
                print "***", fs_item, meta_name
                data = fs_item.meta.get(meta_name, None)
                print "+++", data
                fs_item_data.append(data)

            # Create keyword arguments for the Tkinter field widget
            kwargs = {
                "root": self.root,
                "meta_name": meta_name,
                "fs_item_data": fs_item_data,
                "cfg": self.cfg,
            }

            # Create the Tkinter input widgets
            print "field kwargs:"
            pprint(kwargs)
            field = Field(**kwargs)

            # Store the Tkinter widget for later access
            self.fields[meta_name] = field

            # Create a Tkinter Frame and render the field into it.
            input_frame = fields.MetaInputFrame(
                root = self.root,
                field = field,
                name = meta_name,
                changeable = meta_cfg.get("changeable", True),
            )

    #--------------------------------------------------------------------------

    def _update(self):
        """
        Update the fs_items meta data with the current GUI meta input fields.
        """
        choice_cache = self.cfg["choice cache"]
        meta_data = self.cfg["meta items"]
        print "-"*79
        for meta_name, field in self.fields.iteritems():
            print " -"*40
            print meta_name

            meta_cfg = meta_data[meta_name]
            data = field.get()
            print data

            for item in self.fs_items:
                print "update", item
                item.meta[meta_name] = data
                item.meta.debug()


    def save(self, event=None):
        start_time = time.time()
        self._update()
        for item in self.fs_items:
            item.meta.save()
        print "Saved in %.2fsec" % (time.time() - start_time)
        self.cfg.save()
        self.destroy()

    #--------------------------------------------------------------------------

    def validate(self, event=None):
        start_time = time.time()
        self._update()
        for item in self.fs_items:
            item.meta.debug()
        print "validate in %.2fsec" % (time.time() - start_time)

    #--------------------------------------------------------------------------

    def remove_meta(self, event=None):
        RemoveMetaDialog(self.root, self.fs_items)

    #--------------------------------------------------------------------------

    def create_virtualize(self, event=None):
        virtualizeDialog.CreateVirtualizeDialog(
            self.root, self.fs_items, self.cfg
        )

    def delete_virtualize(self, event=None):
        virtualizeDialog.DeleteVirtualizeDialog(
            self.root, self.fs_items, self.cfg
        )

    #--------------------------------------------------------------------------

    def new(self, event=None):
        self.textfield.insert(tk.END, "\nFile/New\n")

    def open(self, event=None):
        self.textfield.insert(tk.END, "\nFile/Open\n")

    def about(self, event=None):
        tkMessageBox.showinfo(title = "about", message = "python simledms")

    def destroy(self, event=None):
        close = tkMessageBox.askyesno(title="close?", message="Quit?")
        if close:
            self.root.destroy()

    def setup_fields(self, event=None):
        SetupFieldsDialog(self.root)

    def edit_raw_config(self, event=None):
        RawConfigEditDialog(self.root, self.cfg)

    #--------------------------------------------------------------------------

    def _install_info(self):
        command = '"%s" "%s" "%%1" %%*' % (
            sys.executable, os.path.abspath(__file__)
        )
        extensions = ["AllFileSystemObjects"]# "*", "Folder"
        return (extensions, "simpleDMS", command)

    def install(self, event=None):
        """
        install simpleDMS into the explorer context menu
        """
        extensions, context_name, command = self._install_info()
        try:
            context_menu.install(extensions, context_name, command)
        except Exception, err:
            msg = (
                "Can't add simpleDMS into the explorer context menu!\n\n"
                "%s\n\n"
                "(Try to run as a administrator)"
            ) % err
            tkMessageBox.showinfo(title = "error", message = msg)
        else:
            tkMessageBox.showinfo(title = "installed",
                message = (
                    "simpleDMS is installed into the explorer context menu!"
                )
            )       
        
    def deinstall(self, event=None):
        """
        remove simpleDMS from the explorer context menu 
        """
        extensions, context_name, command = self._install_info()
        context_menu.deinstall(extensions, context_name)
        tkMessageBox.showinfo(title = "deinstalled",
            message = "simpleDMS removed from the explorer context menu!"
        ) 
        

    #--------------------------------------------------------------------------

    def help_dialog(self, event=None):
        fn=os.path.join(
            os.path.abspath(os.path.dirname(__file__)),HELP_FILENAME
        )
        textView.TextViewer(self.root,'simpledms help', fn)




if __name__ == '__main__':
    args = sys.argv[1:]
    if not args:
        print "Info: No dir/files given!!!"
        print "args:", args
        
        # For development only!!!
        args = []
        path = "example"
        for filename in os.listdir(path):
            args.append(os.path.join(path, filename))
        
    else:
        print "Add metadata to: %r" % args

    try:
        SimpledmsApp(args)
    except Exception, err:
        print "Error:", err
        print "-"*79
        import traceback
        print traceback.format_exc()
        print "-"*79
        raw_input("ENTER")